package com.library.util;

import com.library.common.utils.RandomCodeUtil;

import java.math.BigDecimal;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicLong;

public class Common1Util {
	private static Common1Util singletonLazy;

	private Common1Util() {

	}

	public static Common1Util getInstance() {
		try {
			if (null == singletonLazy) {
				// 模拟在创建对象之前做一些准备工作
				Thread.sleep(1000);
				synchronized (RandomCodeUtil.class) {
					if (null == singletonLazy) {
						singletonLazy = new Common1Util();
					}
				}
			}
		} catch (InterruptedException e) {
			// TODO: handle exception
		}
		return singletonLazy;
	}

	/**
	 * 解析obj成long
	 * 
	 * @param obj
	 * @return
	 */
	public long praseToLong(Object obj) {
		try {
			if (obj == null) {
				return 0l;
			}
			long longValue = (long) obj;
			return longValue;
		} catch (Exception e) {
			System.out.println("long 转换出错：" + e.getMessage());
			return 0l;
		}
	}

	/**
	 * 解析obj成long
	 * 
	 * @param obj
	 * @return
	 */
	public BigDecimal praseToDecimal(Object obj) {
		try {
			if (obj == null) {
				return BigDecimal.ZERO;
			}
			BigDecimal strValue = (BigDecimal) obj;
			return strValue;
		} catch (Exception e) {
			System.out.println("BigDecimal转换出错：" + e.getMessage());
			return BigDecimal.ZERO;
		}
	}

	public static String getCode() {
		return (int) ((Math.random() * 9 + 1) * 100000) + "";
	}

	private static long tmpID = 0;

	private static boolean tmpIDlocked = false;

	public static long getId() {
		long ltime = 0;
		while (true) {
			if (tmpIDlocked == false) {
				tmpIDlocked = true;
				// 当前：（年、月、日、时、分、秒、毫秒）*10000
				ltime = Long.valueOf(new SimpleDateFormat("yyMMddhhmmssSSS").format(new Date()).toString());
				if (tmpID < ltime) {
					tmpID = ltime;
				} else {
					tmpID = tmpID + 1;
					ltime = tmpID;
				}
				tmpIDlocked = false;
				return ltime;
			}
		}
	}





    // 使用原子类保证线程安全
    private static final AtomicLong lastTimestamp = new AtomicLong();
    private static final AtomicLong sequence = new AtomicLong(0);

    // 时间格式器（线程安全）
    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyMMddHHmmssSSS")
            .withZone(ZoneId.systemDefault());

    // 最大序列号（防止溢出）
    private static final long MAX_SEQUENCE = 9999L;

    public static long getId1() {
        while (true) {
            long currentTimestamp = getCurrentTimestamp();
            long lastTs = lastTimestamp.get();

            if (currentTimestamp > lastTs) {
                if (lastTimestamp.compareAndSet(lastTs, currentTimestamp)) {
                    sequence.set(0);
                    return combineTimestampAndSequence(currentTimestamp, 0);
                }
            } else if (currentTimestamp == lastTs) {
                long seq = sequence.incrementAndGet();
                if (seq <= MAX_SEQUENCE) {
                    return combineTimestampAndSequence(currentTimestamp, seq);
                }
                // 序列号溢出，等待下一毫秒
                waitNextMillis(currentTimestamp);
            } else {
                // 处理时钟回拨（根据业务需求选择策略）
                throw new RuntimeException("Clock moved backwards");
            }
        }
    }

    private static long getCurrentTimestamp() {
        String timestampStr = FORMATTER.format(Instant.now());
        return Long.parseLong(timestampStr);
    }

    private static long combineTimestampAndSequence(long timestamp, long sequence) {
        return timestamp  + sequence;
    }

    private static void waitNextMillis(long currentTimestamp) {
        while (currentTimestamp == getCurrentTimestamp()) {
            Thread.yield();
        }
    }




	/**
	 * 生成 uuid， 即用来标识一笔单，也用做 nonce_str
	 * @return
	 */
	public static String generateUUID(){
		String uuid = UUID.randomUUID().toString().
				replaceAll("-","").substring(0,32);

		return uuid;
	}


	/**
	 * md5常用工具类
	 * @param data
	 * @return
	 */
	public static String MD5(String data){
		try {

			MessageDigest md5 = MessageDigest.getInstance("MD5");
			byte [] array = md5.digest(data.getBytes("UTF-8"));
			StringBuilder sb = new StringBuilder();
			for (byte item : array) {
				sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
			}
			return sb.toString().toUpperCase();

		}catch (Exception e){
			e.printStackTrace();
		}
		return null;

	}


	public static void main(String[] args) {
		System.out.println(Common1Util.getId());
		System.out.println(Common1Util.getId());
		System.out.println(Common1Util.getId());
		System.out.println(Common1Util.getId());
		System.out.println(Common1Util.getId());
		System.out.println(Common1Util.getId());
	}
	
	 
}
